package configx

import (
	"fmt"

	"gitee.com/zhongguo168a/gocodes/datax"
	"gitee.com/zhongguo168a/gocodes/datax/mapx"
	"gitee.com/zhongguo168a/gocodes/datax/schemax"
)

func NewTreeItemByConf(编号 string, conf datax.M) *ConfigTreeItem {
	obj := &ConfigTreeItem{}
	if conf != nil {
		obj.L类型 = mapx.String(conf, "_type")
		obj.M名称 = mapx.String(conf, "_name")
		obj.M命令空间 = mapx.String(conf, "_namespace")
		obj.F分类 = mapx.String(conf, "_catalog")
		obj.F父编号 = mapx.String(conf, "_parent")
		obj.M默认 = mapx.Bool(conf, "_default")
		obj.B编辑器前缀 = mapx.String(conf, "_prefix")
		obj.B编辑器后缀 = mapx.String(conf, "_suffix")
		obj.B编辑器数据 = mapx.String(conf, "_editor")
		obj.W文件 = mapx.String(conf, "_file")
		obj.D导出 = mapx.Int(conf, "_export")
		obj.W唯一的 = mapx.Bool(conf, "_unique")

	}
	obj.B编号 = 编号
	return obj
}

func NewTreeItem(编号 string, 类型 string) *ConfigTreeItem {
	obj := &ConfigTreeItem{}
	obj.L类型 = 类型
	obj.B编号 = 编号
	//[obj.分类编号, obj.分类] = 编号.split("@");

	return obj
}

type ConfigTreeItem struct {

	/**
	 * 由类型和类型编号组成
	 * 格式为：分类编号@分类
	 */
	B编号 string

	F父编号  string
	M命令空间 string

	// 未处理的数据
	原始数据 map[string]interface{}

	/**
	 * 处理后，完整的配置数据
	 */
	数据 map[string]interface{}

	/**
	 * 配置所在的文件路径
	 */
	W文件 string
	/**
	 * 配置的分类
	 * 例如单位，技能，掉落
	 */
	F分类 string

	/**
	 * 配置的对象类型
	 * 例如技能-攻击，技能-移动，技能-效果
	 */
	L类型 string

	M名称  string
	W唯一的 bool

	B编辑器前缀 string

	B编辑器后缀 string
	B编辑器数据 string

	M默认 bool
	D导出 int
}

func (c *ConfigTreeItem) GetClassIdent() string {
	if c.M命令空间 != "" {
		return c.M命令空间 + "/" + c.L类型
	}
	return c.L类型
}
func (c *ConfigTreeItem) Get原始数据() map[string]interface{} {
	return c.原始数据
}
func (c *ConfigTreeItem) Set原始数据(val map[string]interface{}) {
	c.原始数据 = val
}

func (c *ConfigTreeItem) Get数据() map[string]interface{} {
	return c.数据
}
func (c *ConfigTreeItem) Set数据(val map[string]interface{}) {
	c.数据 = val
}

func (c *ConfigTreeItem) GetSchema() *schemax.ClassDecl {
	if c.L类型 == "" {
		return nil
	}
	idecl := schemax.GetDeclByKey(c.L类型)
	if idecl == nil {
		return nil
	}
	return idecl.(*schemax.ClassDecl)
}

func (c *ConfigTreeItem) ToMap() map[string]interface{} {
	m := datax.M{}
	mapx.Copy(c.Get数据(), m)
	m["_type"] = c.L类型
	m["_catalog"] = c.F分类
	m["_parent"] = c.F父编号
	m["_namespace"] = c.M命令空间
	m["_default"] = c.M默认
	m["_prefix"] = c.B编辑器前缀
	m["_suffix"] = c.B编辑器后缀
	m["_editor"] = c.B编辑器数据
	m["_file"] = c.W文件
	m["_export"] = c.D导出
	m["_name"] = c.M名称
	m["_unique"] = c.W唯一的
	return m
}
func (c *ConfigTreeItem) BaseToMap() map[string]interface{} {
	m := datax.M{}
	m["_type"] = c.L类型
	m["_catalog"] = c.F分类
	m["_parent"] = c.F父编号
	m["_namespace"] = c.M命令空间
	m["_default"] = c.M默认
	m["_prefix"] = c.B编辑器前缀
	m["_suffix"] = c.B编辑器后缀
	m["_editor"] = c.B编辑器数据
	m["_file"] = c.W文件
	m["_export"] = c.D导出
	m["_name"] = c.M名称
	m["_unique"] = c.W唯一的
	return m
}

// 继承
func (c *ConfigTreeItem) Inherit(新的编号 string) *ConfigTreeItem {
	obj := &ConfigTreeItem{}
	obj.B编号 = 新的编号
	obj.L类型 = c.L类型
	obj.M名称 = c.M名称
	obj.M命令空间 = c.M命令空间
	obj.F分类 = c.F分类
	obj.F父编号 = c.B编号
	obj.M默认 = c.M默认
	obj.B编辑器前缀 = c.B编辑器前缀
	obj.B编辑器后缀 = c.B编辑器后缀
	obj.W文件 = c.W文件
	obj.D导出 = c.D导出
	obj.W唯一的 = c.W唯一的
	if obj.数据 == nil {
		obj.数据 = map[string]interface{}{}
	}
	mapx.Copy(c.Get数据(), obj.数据)
	return obj
}

func (c *ConfigTreeItem) WalkField(visitor func(classDecl *schemax.ClassDecl, field *schemax.Field, val interface{})) {
	if visitor == nil {
		return
	}

	decl := c.GetSchema()
	if decl == nil {
		panic("Config.WalkField 未发现声明: " + c.L类型)
	}
	c.walkClassDecl(visitor, decl, c.Get数据())
}

func (c *ConfigTreeItem) walkClassDecl(visitor func(classDecl *schemax.ClassDecl, field *schemax.Field, val interface{}), classDecl *schemax.ClassDecl, 数据 map[string]interface{}) {
	allFields := classDecl.GetAllField()
	for _, field := range allFields {
		iFieldVal := 数据[field.Alias()]
		visitor(classDecl, field, iFieldVal)

		switch ftyp := field.Type.(type) {
		case *schemax.ClassType:
			idecl := schemax.GetDeclByKey(ftyp.Decl)
			if idecl == nil {
				panic("未发现声明: " + ftyp.Decl)
			}
			if iFieldVal == nil {
				continue
			}
			fieldVal, ok := iFieldVal.(map[string]interface{})
			if !ok {
				panic(fmt.Sprintf("id=%v, class=%s, field=%v, value=%v", c.B编号, classDecl.Name, field.Name, fieldVal))
			}
			c.walkClassDecl(visitor, idecl.(*schemax.ClassDecl), fieldVal)
		case *schemax.AnyType:
			_type := ftyp.String()
			idecl := schemax.GetDeclByKey(_type)
			if idecl == nil {
				panic("未发现声明: " + _type)
			}
			if iFieldVal == nil {
				continue
			}

			c.walkClassDecl(visitor, idecl.(*schemax.ClassDecl), iFieldVal.(map[string]interface{}))

		}

	}
}
